package com.cqgc.controller;

import cn.hutool.jwt.Claims;
import com.cqgc.pojo.dto.UserDTO.*;
import com.cqgc.pojo.entity.PageResult;
import com.cqgc.pojo.entity.Result;
import com.cqgc.pojo.entity.User;
import com.cqgc.service.UserService;
import com.cqgc.utils.AliyunSmsUtil;
import com.cqgc.utils.JwtUtil;
import com.cqgc.utils.RandomUtil;
import com.cqgc.utils.ThreadLocalUtil;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.shiro.authz.annotation.RequiresRoles;
import org.apache.shiro.util.StringUtils;
import org.hibernate.validator.constraints.URL;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;

@RestController
@RequestMapping("/user")
@Api(tags = "用户接口")
public class UserController {
    @Autowired
    private UserService userService;
    @Resource
    RedisTemplate<String, String> redisTemplate;
    @Autowired
    private AliyunSmsUtil aliyunSmsUtil;
    @Autowired
    StringRedisTemplate stringRedisTemplate;

    @PostMapping("/send/{phone}")
    @ApiImplicitParams({
            @ApiImplicitParam(name = "phone", value = "手机号码", required = true, dataType = "string", paramType = "path")
    })
    @ApiOperation("短信接口")
    public Result sendCode(@PathVariable String phone) {
        // 1. 从Redis中获取验证码
        String code = (String) redisTemplate.opsForValue().get(phone);
        System.out.println("获取到的验证码,{}" + code);
        if (code == null) {
            // 2. 如果Redis中没有验证码记录，生成一个新的四位随机验证码
            String random = RandomUtil.getFourBitRandom();
            // 3. 将新生成的验证码存储在Redis中，设置有效期为5分钟
            redisTemplate.opsForValue().set(phone, random, 5, TimeUnit.MINUTES);
            // 4. 调用阿里云接口发送短信，将验证码发送给指定的手机号码
            boolean b = aliyunSmsUtil.sendSms(phone, random);
            System.out.println("短信发送状态" + b);
            return Result.success("发送成功", random);
        } else {
            // 5. 如果Redis中已存在验证码，说明已经发送过验证码，返回一个成功的响应，提示用户不要重复发送
            return Result.success("请勿重复发送验证码");
        }
    }

    /**
     * 添加用户
     */
    @PostMapping("/add")
    @ApiOperation("添加用户")
    @RequiresRoles("admin")
    public Result add(@RequestBody @Validated AddUserDTO user) {
        User user1 = userService.findAccount(user.getPhone());
        if (user1 != null) {
            return Result.error("手机号已存在");
        }
        int i = userService.add(user);
        System.out.println(i);
        if (i > 0) {
            return Result.success("添加成功");
        }
        return Result.error("添加失败");
    }

    /**
     * 处理用户登录请求。
     *
     * @param user     包含用户登录信息的DTO（数据传输对象），如用户名、密码、验证码等。
     * @param response HTTP响应对象，用于设置登录成功后的Token。
     * @return 返回登录结果，成功则包含成功信息，失败则包含错误信息。
     */
    @PostMapping("/login")
    @ApiOperation("用户登录")
    public Result login(@RequestBody UserLoginDTO user, HttpServletResponse response) {
        // 验证码校验逻辑
        String imageCode = user.getImagecode();
        String captchaKey = user.getCaptchakey();
        if (captchaKey == null) {
            return Result.error("验证码key不能为空");
        }
        String code = redisTemplate.opsForValue().get("captcha:" + user.getCaptchakey());
        if (imageCode.isEmpty() || !imageCode.equals(code)) {
            return Result.error("验证码错误");
        }
        // 用户登录逻辑
        User loginResult = userService.login(user);
        if (loginResult == null) {
            // 登录失败，增加失败尝试次数
            userService.incrementFailedLoginAttempts(user.getAccount());
            if (userService.isAccountLocked(user.getAccount())) {
                return Result.error("账号被锁定,请5分钟后稍后重试");
            }
            return Result.error("账号或密码错误");
        }
        // 账号锁定逻辑检查
        if (userService.isAccountLocked(user.getAccount())) {
            return Result.error("账号被锁定,请5分钟后稍后重试");
        } else {
            int role = userService.findRoleByUid(loginResult.getUid());
            // 登录成功，设置Token
            JwtUtil jwtUtil = new JwtUtil();
            Map<String, Object> map = new HashMap<>();
            map.put("uid", loginResult.getUid());
            map.put("account", loginResult.getAccount());
            String token = jwtUtil.genToken(map);
            Map<String, Object> userMap = new HashMap<>();
            User serviceByUser = userService.findByUser(loginResult.getUid());
            userMap.put("uid", loginResult.getUid());
            userMap.put("account", loginResult.getAccount());
            userMap.put("role", role);
            userMap.put("nickName", serviceByUser.getNickName());

//            jwtUtil.parseToken(token);
            stringRedisTemplate.opsForValue().set(loginResult.getAccount() + "token", token, 12, TimeUnit.HOURS);
            response.setHeader("Authorization", token);
            userService.resetFailedLoginAttempts(user.getAccount());
//            response.setHeader("Access-control-Expose-Headers", "Authorization");
            return Result.success(token, userMap);
        }
        // 登录成功信息
        //return Result.success("用户登录成功");
    }

    @PostMapping("/forget")
    @ApiOperation("忘记密码")
    public Result forget(@RequestBody @Validated UserForgetDTO userForgetDTO) {
        if (!userForgetDTO.getPhone().equals(userForgetDTO.getAccount())) {
            return Result.error("手机号与账号不一至,请确认后再操作");
        }
        User user = userService.findByUsernameAndPhoneNumber(userForgetDTO);
        if (user == null) {
            return Result.error("用户不存在");
        }
        if (user.getState() == 0) {
            return Result.error("账号已停用，请联系管理员");
        }
        String phone = user.getPhone();
        String s = redisTemplate.opsForValue().get(phone);
        if (!userForgetDTO.getPhoneCode().equals(s)) {
            return Result.error("输入的验证码错误");
        }
        if (!userForgetDTO.getNewPassword().equals(userForgetDTO.getCofirmPassword())) {
            return Result.error("两次输入的密码不一致");
        }
        User user1 = new User();
        user1.setPassword(userForgetDTO.getCofirmPassword());
        user1.setAccount(userForgetDTO.getAccount());
        user1.setPhone(userForgetDTO.getPhone());
        int update = userService.update(user1);
        if (update > 0) {
            return Result.success("修改密码成功");
        }
        return Result.error("修改密码失败");
    }


    @PostMapping("/update")
    @ApiOperation("用户更新")
    public Result update(@RequestBody @Validated UpdateUserDTO updateUserDTO) {
        int rows = userService.update1(updateUserDTO);
        if (rows != 0) {
            return Result.success("更新成功");
        }
        return Result.error("更新失败");
    }

    @GetMapping("/delete")
    @ApiOperation("用户删除")
    public Result delete(Integer uid) {
        int rows = userService.delete(uid);
        if (rows != 0) {
            return Result.success("删除成功");
        }
        return Result.error("删除失败");
    }

    @GetMapping("resetPwd")
    @ApiOperation("重置密码")
    public Result resetPwd(Integer uid) {
        int row = userService.resetPwd(uid);
        if (row!=0) {
            return Result.success("重置密码成功");
        }
        return Result.error("重置密码失败");
    }

    @GetMapping("/list")
    @ApiOperation("用户分页查看")
    public Result<PageResult> list(UserPageQueryDTO userPageQueryDTO) {
        PageResult pageResult = userService.list(userPageQueryDTO);
        if (pageResult != null) {
            return Result.success(pageResult);
        }
        return Result.error();
    }

    @PatchMapping("/updatePwd")
    @ApiOperation("修改密码")
    public Result updatePwd(@RequestBody @Validated UpdatePwdDTO updatePwdDTO, @RequestHeader("Authorization") String token) {
        String oldPwd = updatePwdDTO.getOldPwd();
        String newPwd = updatePwdDTO.getNewPwd();
        String rePwd = updatePwdDTO.getRePwd();

        if (!StringUtils.hasLength(oldPwd) || !StringUtils.hasLength(newPwd) || !StringUtils.hasLength(rePwd)) {
            return Result.error("缺少必要的参数");
        }

        Map<String, Object> map = ThreadLocalUtil.get();
        Integer uid = (Integer) map.get("uid");
        String account = (String) map.get("account");
        String password = userService.findPwdByid(uid);

        if (!password.equals(oldPwd)) {
            return Result.error("原密码错误");
        }

        if (!rePwd.equals(newPwd)) {
            return Result.error("两次输入的密码不一致");
        }

        userService.updatePwd(newPwd);
        String key = account + "token";
        Boolean delete = stringRedisTemplate.delete(key);

        System.out.println(delete);
        return Result.success();
    }

    @PostMapping("/register")
    @ApiOperation("用户注册")
    public Result register(@RequestBody @Validated UserRegisterDTO userRegisterDTO) {
        UserRegisterDTO u = userService.findUserByPhone(userRegisterDTO.getPhone());
        if (u != null) {
            return Result.error("该手机号已注册");
        }
        int rows = userService.register(userRegisterDTO);
        if (rows != 0) {
            return Result.success("注册成功");
        }
        return Result.error();

    }

    @PostMapping("/logout")
    @ApiOperation("用户登出")
    public Result logout(@RequestHeader("token") String token) {
        //删除redis中的token
        Map<String, Object> map = JwtUtil.parseToken(token);
        String account = (String) map.get("account");
        System.out.println(account);
        if (redisTemplate.delete(account + "token")) {
            return Result.success("您已安全退出系统");
        }
        return Result.error("退出失败");

    }

    @GetMapping("/findUserByRole")
    @ApiOperation("根据角色id查询用户")
    public Result findUserByRole(Integer rid) {
        List<User> user = userService.findUserByRole(rid);
        return Result.success(user);
    }

    @PostMapping("/updateAvatar")
    @ApiOperation("更新头像")
    public Result updateAvatar(@RequestBody UpdateUserAvatarDTO updateUserAvatarDTO) {
        userService.updateAvatar(updateUserAvatarDTO);
        return Result.success();
    }

    @GetMapping("/getImgUrl")
    @ApiOperation("获取头像")
    public Result getImgUrl() {
        String url = userService.getImgUrl();
        return Result.success(url);
    }

    @GetMapping("/detail")
    @ApiOperation("用户详细")
    public Result getUserByUid(Integer uid) {
        User u = userService.findByUser(uid);
        return Result.success(u);
    }

    @PostMapping("findUserByIf")
    @ApiOperation("根据条件查询用户")
    public Result<PageResult> findUserByIf(@RequestBody LikeUserDTO likeUserDTO){
        PageResult pageResult = userService.findUserByIf(likeUserDTO);
        if (pageResult != null) {
            return Result.success(pageResult);
        }
        return Result.error("无数据");
    }
}
